// Copyright 2022 jeff.li. and/or its affiliates.

#include <tbir/runtime/regex/regex_helper.h>
#include <tbir/runtime/regex/regex_pattern.h>

namespace tbir::runtime::regex {

    std::unique_ptr<RegexPattern> RegexPattern::Load(const String &pattern,
                                                     String *errmsg,
                                                     unsigned int pcre_opt) {
        auto ptr = std::unique_ptr<RegexPattern>(new RegexPattern());
        ptr->pattern_ = pattern;
        ptr->comp_ = RegexHelper::Compile(ptr->pattern_.c_str(), errmsg, pcre_opt);
        if (ptr->comp_ == nullptr) {
            throw std::runtime_error("Failed to compile regex:" + ptr->pattern_);
        }
        return ptr;
    }

    RegexPattern::RegexPattern() : comp_(nullptr), pattern_() {
    }

    RegexPattern::~RegexPattern() {
        if (comp_) {
            RegexHelper::Free(comp_);
        }
    }

    bool RegexPattern::Find(const string_view &subject,
                            int offset,
                            int *from,
                            int *to,
                            String *errmsg,
                            unsigned int pcre_opt) {
        return RegexHelper::Find(
                comp_, subject.data(), subject.size(), offset, from, to, errmsg, pcre_opt) > 0;
    }

    bool RegexPattern::Split(const string_view &subject,
                             std::vector<String> *result,
                             String *errmsg,
                             unsigned int pcre_opt) {
        return RegexHelper::Split(comp_, subject.data(), subject.size(), result, errmsg, pcre_opt) > 0;
    }

    bool RegexPattern::Match(const string_view &subject,
                             int offset,
                             std::vector<String> *match_array,
                             std::unordered_map<String, int> *match_named,
                             String *errmsg,
                             unsigned int pcre_opt) {
        return RegexHelper::Match(comp_,
                                  subject.data(),
                                  subject.size(),
                                  offset,
                                  match_array,
                                  match_named,
                                  errmsg,
                                  pcre_opt) > 0;
    }

    bool RegexPattern::Sub(const string_view &subject,
                           const string_view &repl,
                           String *result,
                           String *errmsg,
                           unsigned int pcre_opt) {
        return RegexHelper::Sub(comp_,
                                subject.data(),
                                subject.size(),
                                repl.data(),
                                repl.size(),
                                result,
                                errmsg,
                                pcre_opt) > 0;
    }

    bool RegexPattern::GSub(const string_view &subject,
                            const string_view &repl,
                            String *result,
                            String *errmsg,
                            unsigned int pcre_opt) {
        return RegexHelper::GSub(comp_,
                                 subject.data(),
                                 subject.size(),
                                 repl.data(),
                                 repl.size(),
                                 result,
                                 errmsg,
                                 pcre_opt) > 0;
    }

    bool RegexPattern::MatchSub(const string_view &subject,
                                const string_view &repl,
                                String *result,
                                String *errmsg,
                                unsigned int pcre_opt) {
        return RegexHelper::MatchSub(comp_,
                                     subject.data(),
                                     subject.size(),
                                     repl.data(),
                                     repl.size(),
                                     result,
                                     errmsg,
                                     pcre_opt) > 0;
    }

    bool RegexPattern::MatchGSub(const string_view &subject,
                                 const string_view &repl,
                                 String *result,
                                 String *errmsg,
                                 unsigned int pcre_opt) {
        return RegexHelper::MatchGSub(comp_,
                                      subject.data(),
                                      subject.size(),
                                      repl.data(),
                                      repl.size(),
                                      result,
                                      errmsg,
                                      pcre_opt) > 0;
    }

}  // namespace tbir::runtime::regex
